Imports System.Text.RegularExpressions

Namespace Packets

    Module mPackets

        Public Sub PacketIn(ByVal info As Packet, ByVal struct() As Byte, ByRef Conn As Connection)


            Select Case CType(info.PacketType, GenericPacketType)

                'Case GenericPacketType.ClientVersion
                '    Select Case info.PacketOpCode
                '        Case PacketOpCode.Answer
                '            ValidateClientVersion(ArrayToStruct(struct, GetType(ClientVersion)), Conn)
                '        Case Else
                '            Debug.Print("MirEvoSvr.mSocket.Socket.SockServer_onDataArrival: Recieved invalid OpCode with ClientVersion packet")
                '    End Select

                'Case GenericPacketType.Username
                '    Select Case info.PacketOpCode
                '        Case PacketOpCode.Enquiry
                '            GenerateSessionID(Conn)
                '        Case PacketOpCode.Notify
                '            Dim sid As SessionID = ArrayToStruct(struct, GetType(SessionID))

                '            Conn.Username = sid.Username
                '            Conn.Crypto = New Cryptography.Crypto(Cryptography.Functions.UsernameToKey(sid.Username))

                '            Conn.CanLogin = True

                '            CheckXServerConn(Conn)

                '        Case Else
                '            Debug.Print("MirEvoSvr.mSocket.Socket.SockServer_onDataArrival: Recieved invalid OpCode with SessionID packet")
                '    End Select


                Case GenericPacketType.PingTest
                    Select Case info.PacketOpCode
                        Case PacketOpCode.Notify
                            Dim pkt As Packet
                            pkt.PacketType = GenericPacketType.PingTest
                            pkt.PacketOpCode = PacketOpCode.Acknowledge
                            pkt.Username = Conn.Username

                            Socket.SockServer.SendData(Protocol.MakePacket(pkt, , Conn.Crypto), Conn.Index)

                    End Select

                Case GenericPacketType.ClientError
                    Select Case info.PacketOpCode
                        Case PacketOpCode.Notify
                            Dim clienterr As ClientErrorText = ArrayToStruct(struct, GetType(ClientErrorText))
                            Dim err_file As String = Database.Functions.TimeString & "-error.txt"
                            Dim err_path As String = Globals.sServerPath & "\Error\"
                            Dim it As Integer
                            Do Until Not System.IO.File.Exists(err_path & err_file)
                                it += 1
                                err_file = Database.Functions.TimeString & "-(" & it & ")-error.txt"
                            Loop
                            Dim fs As New System.IO.FileStream(err_path & err_file, System.IO.FileMode.Create)
                            Dim bw As New System.IO.BinaryWriter(fs)
                            bw.Write(clienterr.STR)
                            bw.Close()

                    End Select

                Case Else

                    Select Case CType(info.PacketType, LoginPacketType)

                        Case LoginPacketType.TryLogin
                            Select Case info.PacketOpCode
                                Case PacketOpCode.Enquiry
                                    Dim sLogin As UserLogin = ArrayToStruct(struct, GetType(UserLogin))
                                    Dim p As Packet
                                    'set connection username
                                    Conn.Username = sLogin.STR_USERNAME
                                    'check client version string
                                    If sLogin.STR_CLIENTVER = Protocol.sClientVersion Then
                                        Conn.ClientVerOK = True
                                        'valid client version
                                        'sql query string
                                        Dim ssql As String = "SELECT STR_PASSMD5, ID_LOGIN FROM TBL_LOGINS WHERE STR_USERNAME='" & sLogin.STR_USERNAME & "';"
                                        'collection to hold results
                                        Dim row As Collection = DB.AccountDB.ExecuteQueryFirstRecord(ssql)
                                        'setup packet struct for failed login (invalid user)
                                        p.PacketType = LoginPacketType.TryLogin
                                        p.PacketOpCode = PacketOpCode.NegAcknowledge
                                        p.Username = Conn.Username
                                        'check for a result from sql query
                                        If Not row Is Nothing Then
                                            If row.Count > 0 Then
                                                'setup packet struct for magic packet
                                                p.PacketType = LoginPacketType.TryMagicPacket
                                                p.PacketOpCode = PacketOpCode.Enquiry
                                                p.Username = Conn.Username
                                                Conn.Crypto = New Cryptography.Crypto(CStr(row("STR_PASSMD5")))
                                                Conn.LoginID = row("ID_LOGIN")
                                                Conn.CanLogin = True
                                            End If
                                        End If
                                        'send reply packet
                                        If p.PacketOpCode = PacketOpCode.NegAcknowledge Then
                                            'send failure w/ payload of generic message
                                            Dim s As GenericMessage
                                            s.MESSAGE = "Login Failed!"
                                            Socket.SockServer.SendData(MakePacket(p, s, Cryptography.DefaultCrypto), Conn.Index)
                                        Else
                                            'send success and ask for magic packet
                                            Socket.SockServer.SendData(MakePacket(p, , Cryptography.DefaultCrypto), Conn.Index)
                                        End If
                                    Else
                                        'invalid client version
                                        p.PacketType = GenericPacketType.ClientVersion
                                        p.PacketOpCode = Protocol.mProtocol.PacketOpCode.NegAcknowledge
                                        p.Username = Conn.Username
                                        Socket.SockServer.SendData(MakePacket(p, , Cryptography.DefaultCrypto), Conn.Index)
                                    End If


                                Case Else
                                    Debug.Print("MirEvoSvr.mSocket.Socket.SockServer_onDataArrival: Recieved invalid OpCode with TryLogin packet")
                            End Select

                        Case LoginPacketType.TryMagicPacket
                            Select Case info.PacketOpCode
                                Case PacketOpCode.Answer
                                    DoLogin(Conn)
                            End Select

                        Case LoginPacketType.TryNewLogin
                            Select Case info.PacketOpCode
                                Case PacketOpCode.Enquiry
                                    TryNewLogin(ArrayToStruct(struct, GetType(NewUserLogin)), Conn)
                                Case Else
                                    Debug.Print("MirEvoSvr.mSocket.Socket.SockServer_onDataArrival: Recieved invalid OpCode with TryNewLogin packet")

                            End Select

                        Case Else

                            If Conn.ClientVerOK And Conn.CanLogin Then

                                Select Case CType(info.PacketType, LoginPacketType)

                                    'Case LoginPacketType.TryLogin
                                    '    Select Case info.PacketOpCode
                                    '        Case PacketOpCode.Enquiry
                                    '            If Globals.isLoginServer Then
                                    '                DoLogin(ArrayToStruct(struct, GetType(UserLogin)), Conn)
                                    '            Else

                                    '                Dim reply As Packet
                                    '                reply.Username = Conn.Username
                                    '                reply.PacketType = LoginPacketType.TryLogin
                                    '                reply.PacketOpCode = PacketOpCode.NegAcknowledge

                                    '                Dim msg As GenericMessage
                                    '                msg.MESSAGE = "This is not the designated login server for this cluster!"

                                    '                Socket.SockServer.SendData(Protocol.MakePacket(reply, msg, Conn.Crypto), Conn.Index)

                                    '            End If
                                    '        Case Else
                                    '            Debug.Print("MirEvoSvr.mSocket.Socket.SockServer_onDataArrival: Recieved invalid OpCode with TryLogin packet")
                                    '    End Select

                                    Case LoginPacketType.CharList
                                        Select Case info.PacketOpCode
                                            Case PacketOpCode.Enquiry
                                                System.Threading.Thread.Sleep(500)
                                                System.Windows.Forms.Application.DoEvents()

                                                CharList(Conn)

                                                Dim map As MirMap = GetMapFromConn(Conn)
                                                If Not map Is Nothing Then
                                                    'set user offline for httpd stats reporter
                                                    Dim i As PlayerOnlineInfo
                                                    i.ID_CHARACTER = Conn.CharacterID
                                                    i.STR_NAME = Conn.PlayerInfo.STR_NAME
                                                    Socket.HTTPStats.Data.OnlineUsers.Offline(i)

                                                    Conn.IsAlive = False
                                                    'reset the connection object to be logged out
                                                    Socket.SockServer.ConnectionList.SetCharacter(Conn.Index, "", 0, Gender.Male, CharacterJobs.Warrior)
                                                    'remove the player from the game
                                                    mMaps.RemovePlayer(Conn, map)
                                                End If

                                            Case Else
                                                Debug.Print("MirEvoSvr.mSocket.Socket.SockServer_onDataArrival: Recieved invalid OpCode with CharList packet")
                                        End Select

                                    Case LoginPacketType.TryNewChar
                                        Select Case info.PacketOpCode
                                            Case PacketOpCode.Enquiry
                                                TryNewChar(ArrayToStruct(struct, GetType(CreateCharInfo)), Conn)
                                            Case Else
                                                Debug.Print("MirEvoSvr.mSocket.Socket.SockServer_onDataArrival: Recieved invalid OpCode with TryNewChar packet")
                                        End Select

                                    Case LoginPacketType.TryDelChar
                                        Select Case info.PacketOpCode
                                            Case PacketOpCode.Enquiry
                                                TryDelChar(ArrayToStruct(struct, GetType(DelCharRequest)), Conn)
                                            Case Else
                                                Debug.Print("MirEvoSvr.mSocket.Socket.SockServer_onDataArrival: Recieved invalid OpCode with TryDelChar packet")

                                        End Select

                                    Case LoginPacketType.TrySelectChar
                                        Select Case info.PacketOpCode
                                            Case PacketOpCode.Enquiry
                                                TrySelectChar(ArrayToStruct(struct, GetType(SelectCharRequest)), Conn)
                                            Case Else
                                                Debug.Print("MirEvoSvr.mSocket.Socket.SockServer_onDataArrival: Recieved invalid OpCode with TrySelectChar packet")
                                        End Select

                                End Select

                            End If

                            If Conn.CharacterID > 0 Then

                                Select Case CType(info.PacketType, GamePacketType)

                                    Case GamePacketType.PlayerUpdate
                                        Select Case info.PacketOpCode
                                            Case PacketOpCode.Enquiry
                                                TryMoveChar(ArrayToStruct(struct, GetType(PlayerPositionInfo)), Conn)

                                        End Select

                                    Case GamePacketType.ChatMsg
                                        Select Case info.PacketOpCode
                                            Case PacketOpCode.Enquiry
                                                ChatMessage(ArrayToStruct(struct, GetType(ChatMsg)), Conn)
                                        End Select

                                    Case GamePacketType.ChangeItemLocation
                                        Select Case (info.PacketOpCode)
                                            Case PacketOpCode.Notify
                                                ChangeItemLocation(ArrayToStruct(struct, GetType(ItemLocationInfo)), Conn)
                                        End Select

                                    Case GamePacketType.Magic
                                        Select Case info.PacketOpCode
                                            Case PacketOpCode.Enquiry
                                                CastMagic(ArrayToStruct(struct, GetType(MagicCast)), Conn)
                                        End Select

                                    Case GamePacketType.Resync
                                        Select Case info.PacketOpCode
                                            Case PacketOpCode.Enquiry
                                                ResyncPlayer(Conn)
                                        End Select

                                    Case GamePacketType.FloorItemPickup

                                        Select Case info.PacketOpCode
                                            Case PacketOpCode.Enquiry
                                                Dim map As MirMap = GetMapFromConn(Conn)
                                                map.FloorItems.PickupItem(ArrayToStruct(struct, GetType(Int64)), Conn)
                                        End Select

                                    Case GamePacketType.DropItem
                                        Select Case info.PacketOpCode
                                            Case PacketOpCode.Enquiry
                                                Dim item As DropItemRequest = ArrayToStruct(struct, GetType(DropItemRequest))
                                                Dim map As MirMap = GetMapFromConn(Conn)
                                                map.FloorItems.DoDrop(item, Conn)

                                        End Select

                                    Case GamePacketType.MobAddUpdate
                                        Select Case info.PacketOpCode
                                            Case PacketOpCode.Enquiry
                                                Dim id As Int64 = ArrayToStruct(struct, GetType(Int64))
                                                GetMapFromConn(Conn).Mobs.ResyncMob(Conn, id)
                                        End Select

                                    Case GamePacketType.SplitStack
                                        Select Case info.PacketOpCode
                                            Case PacketOpCode.Enquiry
                                                Dim split As SplitStackRequest = ArrayToStruct(struct, GetType(SplitStackRequest))
                                                SplitStack(split, Conn)

                                        End Select

                                    Case GamePacketType.JoinStacks
                                        Select Case info.PacketOpCode
                                            Case PacketOpCode.Enquiry
                                                Dim stacks As JoinStackRequest = ArrayToStruct(struct, GetType(JoinStackRequest))
                                                JoinStacks(stacks, Conn)

                                        End Select

                                    Case GamePacketType.UseItem
                                        Select Case info.PacketOpCode
                                            Case PacketOpCode.Enquiry
                                                Dim id As Int64 = ArrayToStruct(struct, GetType(Int64))
                                                UseItem(id, Conn)
                                        End Select

                                    Case GamePacketType.NPCCall
                                        Select Case info.PacketOpCode
                                            Case PacketOpCode.Enquiry
                                                Dim npc_call As NPCCall = ArrayToStruct(struct, GetType(NPCCall))
                                                Output.AddLine("\B0\F5SS>\F0\B8 " & npc_call.CMD)
                                                If npc_call.ID_NPC > 0 Then
                                                    Conn.SetValue(Constants.SysVarName_NPCID, npc_call.ID_NPC)
                                                End If
                                                ServerScripting.Scripts.SayCall(npc_call.CMD, Conn)
                                        End Select

                                    Case GamePacketType.NPCShopBuy
                                        Select Case info.PacketOpCode
                                            Case PacketOpCode.Enquiry
                                                Dim buy_info As ShopItemBuyInfo = ArrayToStruct(struct, GetType(ShopItemBuyInfo))
                                                Dim map As MirMap = GetMapFromConn(Conn)
                                                If map.NPCs.lstShops.ContainsKey(buy_info.ID_NPC) Then
                                                    GetMapFromConn(Conn).NPCs.lstShops(buy_info.ID_NPC).BuyItem(Conn, buy_info)
                                                End If
                                        End Select

                                    Case GamePacketType.NPCShopLoadItems
                                        Select Case info.PacketOpCode
                                            Case PacketOpCode.Enquiry
                                                Dim items_info As ShopLoadItemsInfo = ArrayToStruct(struct, GetType(ShopLoadItemsInfo))
                                                Dim map As MirMap = GetMapFromConn(Conn)
                                                If map.NPCs.lstShops.ContainsKey(items_info.ID_NPC) Then
                                                    map.NPCs.lstShops(items_info.ID_NPC).ShopLoadItems(Conn, items_info)
                                                End If
                                        End Select

                                    Case GamePacketType.NPCShopSell
                                        Select Case info.PacketOpCode
                                            Case PacketOpCode.Enquiry
                                                Dim sell As ShopItemSellInfo = ArrayToStruct(struct, GetType(ShopItemSellInfo))
                                                Dim map As MirMap = GetMapFromConn(Conn)
                                                If map.NPCs.lstShops.ContainsKey(sell.ID_NPC) Then
                                                    map.NPCs.lstShops(sell.ID_NPC).SellItem(Conn, sell)
                                                End If
                                        End Select

                                    Case GamePacketType.SetSkillMapping
                                        Select Case info.PacketOpCode
                                            Case PacketOpCode.Notify
                                                Dim map As PlayerSkillMapping = ArrayToStruct(struct, GetType(PlayerSkillMapping))
                                                mMagics.DoMapping(Conn, map)

                                                'todo: delete mapping


                                        End Select

                                    Case GamePacketType.FormGroup
                                        Select Case info.PacketOpCode
                                            Case PacketOpCode.Enquiry
                                                Dim name As GroupName = ArrayToStruct(struct, GetType(GroupName))




                                        End Select

                                End Select
                            End If
                    End Select
            End Select

        End Sub

        'Private Sub ValidateClientVersion(ByVal struct As ClientVersion, ByRef Conn As Connection)

        '    Dim reply As Packet
        '    reply.Username = DefaultUsername
        '    reply.PacketType = GenericPacketType.ClientVersion

        '    If struct.CLIENTVER = Protocol.sClientVersion Then
        '        reply.PacketOpCode = PacketOpCode.Acknowledge
        '        Conn.ClientVerOK = True
        '        Socket.SockServer.SendData(Protocol.MakePacket(reply), Conn.Index)
        '    Else
        '        reply.PacketOpCode = PacketOpCode.NegAcknowledge
        '        Conn.ClientVerOK = False
        '        Socket.SockServer.SendData(Protocol.MakePacket(reply), Conn.Index)
        '    End If

        'End Sub

        'Private Sub GenerateSessionID(ByRef Conn As Connection)

        '    If Not Conn.ClientVerOK Then
        '        Socket.SockServer.EndConnection(Conn.Index)
        '        Exit Sub
        '    End If

        '    Dim reply As Packet
        '    reply.Username = DefaultUsername
        '    reply.PacketType = GenericPacketType.Username
        '    reply.PacketOpCode = PacketOpCode.Answer

        '    Dim struct As SessionID
        '    Dim tmp As Byte()
        '    Dim key(15) As Byte
        '    Dim skey As String
        '    Do
        '        tmp = Functions.GenerateSessionID()
        '        skey = Cryptography.Functions.UsernameToKey(tmp)
        '        For i As Integer = 1 To key.Length
        '            key(i - 1) = Asc(Mid(skey, i, 1))
        '        Next
        '        If Not System.Security.Cryptography.TripleDES.IsWeakKey(key) Then
        '            Exit Do
        '        End If
        '    Loop

        '    struct.Username = tmp
        '    Conn.Username = tmp
        '    Conn.Crypto = New Cryptography.Crypto(Cryptography.Functions.UsernameToKey(tmp))

        '    Socket.SockServer.SendData(Protocol.MakePacket(reply, struct), Conn.Index)
        '    Conn.CanLogin = True

        'End Sub

        Public Sub DoLogin(ByRef Conn As Connection)

            'If Not Conn.CanLogin Then
            'Socket.SockServer.EndConnection(Conn.Index)
            'Exit Sub
            'End If

            Dim sSql As String = "SELECT ID_LOGIN, STR_PASSMD5 FROM TBL_LOGINS WHERE STR_USERNAME='" & Conn.Username & "' AND BOOL_DELETED='False';"
            Dim row As Collection = DB.AccountDB.ExecuteQueryFirstRecord(sSql)

            'Dim sMd5 As String = row("STR_PASSMD5")
            'Conn.Crypto = New Cryptography.Crypto(MD5Hash(sMd5))

            Dim reply As Packet
            reply.Username = Conn.Username
            reply.PacketType = LoginPacketType.TryLogin

            Dim msg As GenericMessage
            msg.MESSAGE = "Login failed!"

            Dim sqlerr As Boolean

            If row Is Nothing Then sqlerr = True

            If sqlerr Then

                'sql returned an error, either sql failed or returned nothing
                Socket.SockServer.SendData(Protocol.MakePacket(reply, msg, Cryptography.DefaultCrypto), Conn.Index)
                reply.PacketOpCode = PacketOpCode.NegAcknowledge
                Logger.LoggerWriteLine("DB> !SQL Error while attempting a login! [UName:'" & Conn.Username & "' IP: " & Conn.IP & "]")

            Else

                If row.Count > 0 Then

                    Dim id As Integer = row("ID_LOGIN")

                    If Functions.AccountIsLocked(id) Then
                        'account is locked, and has not yet exceeded the timeout
                        reply.PacketOpCode = PacketOpCode.NegAcknowledge
                        msg.MESSAGE = "Login failed! The account has been locked due to excessive login attempts, it will unlock at " & Functions.GetLockTimeout(Conn.Username) & " " & Globals.ServerTimeZone & "."
                        Logger.LoggerWriteLine("!!> Locked account [" & Conn.Username & "] attempted login from IP [" & Conn.IP & "]")
                    Else

                        ''password matches
                        ''If row("STR_PASSMD5") = uid.STR_PASSMD5 Then
                        'account is not locked
                        Functions.ResetLoginAttempts(id)

                        'check for account ban
                        sSql = "SELECT ID_LOGIN FROM TBL_BAN WHERE ID_LOGIN='" & id & "' AND BOOL_DELETED='FALSE';"
                        row = DB.AccountDB.ExecuteQueryFirstRecord(sSql)

                        Dim isInvalid As Boolean

                        If row Is Nothing Then
                            isInvalid = True
                        ElseIf row.Count = 0 Then
                            isInvalid = True
                        End If

                        If isInvalid Then

                            isInvalid = False

                            'check if user is gm
                            sSql = "SELECT BOOL_IGNOREFILTER FROM TBL_GAMEMASTERLOGINS WHERE ID_LOGIN='" & id & "' AND BOOL_DELETED='FALSE';"
                            row = DB.AccountDB.ExecuteQueryFirstRecord(sSql)

                            If row Is Nothing Then
                                isInvalid = True
                            ElseIf row.Count = 0 Then
                                isInvalid = True
                            End If

                            If Not isInvalid Then
                                'user is gm, check if uses ip filters
                                If row("BOOL_IGNOREFILTER") = False Then
                                    'uses ip filters, check ip is in filter table
                                    sSql = "SELECT * FROM TBL_GAMEMASTERIPFILTER WHERE STR_IP='" & Conn.IP & "' AND BOOL_DELETED='FALSE';"
                                    row = DB.AccountDB.ExecuteQueryFirstRecord(sSql)

                                    If row Is Nothing Then
                                        isInvalid = True
                                    ElseIf row.Count = 0 Then
                                        isInvalid = True
                                    End If

                                    If Not isInvalid Then
                                        'user authenticated as game master
                                        reply.PacketOpCode = PacketOpCode.Acknowledge
                                        Socket.SockServer.ConnectionList.SetLogin(Conn.Index, Conn.Username, id)
                                        Socket.SockServer.ConnectionList.SetToGM(Conn.Index)
                                        Output.AddLine("\F9\B0@GM\B8\F0 GM '\B0\F8" & Conn.Username & "\B8\F0'(\F4" & id & "\F0) logged on")
                                    Else
                                        'ip filter is on and ip is unknown, fail login
                                        reply.PacketOpCode = PacketOpCode.NegAcknowledge
                                        msg.MESSAGE = "GM Login is not permitted from this address!"
                                        Output.AddLine(Constants.SysCmdAttention & " GM Login tried from unauthorised IP [\F3" & Conn.IP & "\F0] Username [\B0\F8" & Conn.Username & "\F0\B8]")
                                    End If
                                Else
                                    'user is authenticated as game master
                                    reply.PacketType = LoginPacketType.TryMagicPacket
                                    reply.PacketOpCode = PacketOpCode.Acknowledge
                                    Socket.SockServer.ConnectionList.SetLogin(Conn.Index, Conn.Username, id)
                                    Socket.SockServer.ConnectionList.SetToGM(Conn.Index)
                                    Output.AddLine("\B0\F5SV>\B8\F0 @GM GM '\B0\F8" & Conn.Username & "\F0\B8'(" & id & ") logged on")

                                End If
                            Else
                                'user has logged in
                                If Globals.bUnderMaintainance Then

                                    reply.PacketOpCode = PacketOpCode.NegAcknowledge
                                    msg.MESSAGE = "Under Maintainance; GM Login is not permitted for this Account!"
                                    Output.AddLine(Constants.SysCmdAttention & " Login tried for Username [\B0\F8" & Conn.Username & "\F0\B8] server under maintainance")

                                Else
                                    reply.PacketType = LoginPacketType.TryMagicPacket
                                    reply.PacketOpCode = PacketOpCode.Acknowledge
                                    Socket.SockServer.ConnectionList.SetLogin(Conn.Index, Conn.Username, id)
                                    Output.AddLine("\B0\F5SV>\B8\F0 >>> User '\B0\F8" & Conn.Username & "\F0\B8' (" & id & ") logged on")
                                End If
                            End If

                        Else
                            'account is banned
                            reply.PacketOpCode = PacketOpCode.NegAcknowledge
                            msg.MESSAGE = "This account is banned"
                            Logger.LoggerWriteLine("!!! Banned account [" & Conn.Username & "] attempted login from IP [" & Conn.IP & "]")
                        End If

                        ''Else

                        ''password invalid

                        ''End If

                    End If

                End If

            End If

            If reply.PacketOpCode = PacketOpCode.Acknowledge Then
                Socket.SockServer.SendData(Protocol.MakePacket(reply, , Conn.Crypto), Conn.Index)
            Else
                Socket.SockServer.SendData(Protocol.MakePacket(reply, msg, Cryptography.DefaultCrypto), Conn.Index)
                Conn.CanLogin = False
                Conn.ClientVerOK = False
                Conn.Crypto = Nothing
                Conn.Username = Protocol.DefaultUsername
            End If

        End Sub

        Public Sub SendInvalidPwdPacket(ByRef conn As Connection)

            Dim sSql As String = "SELECT ID_LOGIN FROM TBL_LOGINS WHERE STR_USERNAME='" & conn.Username & "' AND BOOL_DELETED='False';"
            Dim row As Collection = DB.AccountDB.ExecuteQueryFirstRecord(sSql)

            Dim reply As Packet
            reply.Username = Protocol.DefaultUsername
            reply.PacketType = LoginPacketType.TryLogin

            Dim msg As GenericMessage
            msg.MESSAGE = "Login failed!"

            Functions.FailedLogin(row("ID_LOGIN"))
            Output.AddLine(Constants.SysCmdAttention & " Failed login for account [\B0\F8" & conn.Username & "\F0\B8] from IP [\B0\F8" & conn.IP & "\F0\B8]")
            conn.Crypto = Cryptography.DefaultCrypto
            conn.Username = Protocol.DefaultUsername
            conn.CanLogin = False
            conn.ClientVerOK = False
            reply.PacketOpCode = PacketOpCode.NegAcknowledge

            Socket.SockServer.SendData(Protocol.MakePacket(reply, msg, Cryptography.DefaultCrypto), conn.Index)

        End Sub

        Private Sub CharList(ByRef Conn As Connection)

            Dim reply As Packet
            reply.Username = Conn.Username
            reply.PacketType = LoginPacketType.CharList
            reply.PacketOpCode = PacketOpCode.Answer

            Dim struct As SelCharList = Functions.GetSelCharList(Conn.LoginID)

            If struct.CHAR_1.ID_CHARACTER > 0 Then

                Socket.SockServer.SendData(Protocol.MakePacket(reply, struct, Conn.Crypto), Conn.Index)

            Else

                reply.PacketOpCode = PacketOpCode.NegAcknowledge
                Socket.SockServer.SendData(Protocol.MakePacket(reply, , Conn.Crypto), Conn.Index)

            End If
        End Sub

        Private Sub TryNewChar(ByVal struct As CreateCharInfo, ByRef Conn As Connection)

            Dim sql As String = "SELECT ID_CHARACTER FROM TBL_CHARACTER WHERE STR_NAME='" & struct.STR_NAME & "';"
            Dim row As Collection = DB.GameDB.ExecuteQueryFirstRecord(sql)

            Dim reply As Packet
            reply.Username = Conn.Username
            reply.PacketType = LoginPacketType.TryNewChar

            If row Is Nothing Then
                Exit Sub
            End If

            If row.Count = 0 Then

                If Functions.HasSpareSlots(Conn.LoginID) Then

                    Dim cols() As String = {"ID_LOGIN", "STR_NAME", "BOOL_DELETED", "STR_CREATED", "STR_LASTLOGIN", "BYTE_JOB", "BYTE_SEX", "STR_STORAGEPASSMD5", "BYTE_HAIR", "BYTE_HAIRCOL", "BOOL_SHOWHELM", "INT8_GOLD", "INT8_GAMEGOLD", "INT8_FAMEPOINTS", "STR_HOMEMAP"}
                    Dim vals() As String = {Conn.LoginID, "'" & struct.STR_NAME & "'", "'FALSE'", "'" & Database.Functions.TimeString & "'", "''", struct.BYTE_JOB, struct.BYTE_SEX, "''", 0, System.Drawing.Color.Brown.ToArgb, "'False'", 0, 0, 0, Globals.iniServer.GetString("NEWCHAR", "MAP", "0")}

                    Dim idChar As Int64 = DB.GameDB.NewRecord("TBL_CHARACTER", cols, vals)

                    If idChar > 0 Then

                        'Functions.WriteBlankEquipment(idChar)
                        Functions.WriteFreshBaseStats(idChar, struct.BYTE_JOB)
                        Functions.SetSelectedChar(Conn.LoginID, struct.STR_NAME)
                        reply.PacketOpCode = PacketOpCode.Acknowledge
                        Socket.SockServer.SendData(Protocol.MakePacket(reply, , Conn.Crypto), Conn.Index)

                    Else
                        'failed!
                        reply.PacketOpCode = PacketOpCode.NegAcknowledge
                        Dim msg As GenericMessage
                        msg.MESSAGE = "Character creation failed!"
                        Socket.SockServer.SendData(Protocol.MakePacket(reply, msg, Conn.Crypto), Conn.Index)

                    End If

                Else
                    'no spare slots!
                    reply.PacketOpCode = PacketOpCode.NegAcknowledge
                    Dim msg As GenericMessage
                    msg.MESSAGE = "You already have the maximum number of characters!"
                    Socket.SockServer.SendData(Protocol.MakePacket(reply, msg, Conn.Crypto), Conn.Index)

                End If

            Else
                'character already exists with name!
                reply.PacketOpCode = PacketOpCode.NegAcknowledge
                Dim msg As GenericMessage
                msg.MESSAGE = "A character already exists with that name!"
                Socket.SockServer.SendData(Protocol.MakePacket(reply, msg, Conn.Crypto), Conn.Index)

            End If

        End Sub

        Private Sub TryDelChar(ByVal struct As DelCharRequest, ByRef Conn As Connection)

            Dim sSql As String = "SELECT STR_PASSMD5 FROM TBL_LOGINS WHERE ID_LOGIN=" & Conn.LoginID & ";"
            Dim row As Collection = DB.AccountDB.ExecuteQueryFirstRecord(sSql)

            Dim sqlerr As Boolean

            If row Is Nothing Then sqlerr = True
            If row.Count = 0 Then sqlerr = True

            Dim reply As Packet
            reply.Username = Conn.Username
            reply.PacketType = LoginPacketType.TryDelChar

            Dim msg As GenericMessage

            If sqlerr Then
                msg.MESSAGE = "Character deletion failed! (SQL Failiure)"
                GoTo fail
            End If

            If row("STR_PASSMD5") = struct.STR_PASSMD5 Then

                sSql = "UPDATE TBL_CHARACTER SET BOOL_DELETED='True' WHERE ID_CHARACTER=" & struct.ID_CHARACTER & " AND ID_LOGIN=" & Conn.LoginID & ";"
                Dim result As Integer = DB.GameDB.ExecuteNonQuery(sSql)

                If result = 0 Then

                    msg.MESSAGE = "Character deletion failed!"
                    GoTo fail

                Else

                    Functions.SetSelectedChar(Conn.LoginID, "")
                    reply.PacketOpCode = PacketOpCode.Acknowledge
                    Socket.SockServer.SendData(Protocol.MakePacket(reply, , Conn.Crypto), Conn.Index)

                End If


            Else

                msg.MESSAGE = "Invalid password!"
                GoTo fail

            End If

            Exit Sub

fail:

            reply.PacketOpCode = PacketOpCode.NegAcknowledge
            Socket.SockServer.SendData(Protocol.MakePacket(reply, msg, Conn.Crypto), Conn.Index)

        End Sub

        Private Sub TryNewLogin(ByVal struct As NewUserLogin, ByRef Conn As Connection)


            Dim msg As New GenericMessage
            Dim reply As Packet
            reply.Username = Protocol.DefaultUsername
            reply.PacketType = LoginPacketType.TryNewLogin

            Dim ret As Boolean = Functions.CreateAccount(struct, False, False, msg.MESSAGE)

            If ret Then
                reply.PacketOpCode = PacketOpCode.Acknowledge
            Else
                reply.PacketOpCode = PacketOpCode.NegAcknowledge
            End If

            Socket.SockServer.SendData(Protocol.MakePacket(reply, msg, Cryptography.DefaultCrypto), Conn.Index)

        End Sub

        Public Sub TrySelectChar(ByVal struct As SelectCharRequest, ByRef Conn As Connection, Optional loadmap As Boolean = True)

            Dim ssql As String = "SELECT ID_LOGIN, STR_NAME, BYTE_SEX, BYTE_JOB, STR_LASTLOGIN FROM TBL_CHARACTER WHERE ID_CHARACTER=" & struct.ID_CHARACTER & ";"
            Dim row As Collection = DB.GameDB.ExecuteQueryFirstRecord(ssql)

            Dim reply As Packet
            reply.Username = Conn.Username
            reply.PacketType = LoginPacketType.TrySelectChar

            If row Is Nothing Then GoTo fail
            If row.Count = 0 Then GoTo fail

            If row("ID_LOGIN") = Conn.LoginID Then

                Socket.SockServer.ConnectionList.SetCharacter(Conn.Index, row("STR_NAME"), struct.ID_CHARACTER, row("BYTE_SEX"), row("BYTE_JOB"))

                'check if this is the first login for this character
                If row("STR_LASTLOGIN") = "" Then

                    'run the first login script
                    ServerScripting.Scripts.RunCommand("login.txt", "@onfirstlogin", Conn)
                    Windows.Forms.Application.DoEvents()
                    Threading.Thread.Sleep(1000)

                End If

                Conn.PlayerWeight = New PlayerWeights

                'TODO: full player type code
                If Conn.IsGM Then Conn.PlayerInfo.TYPE = PlayerType.DEV

                LoadPlayerLooks(Conn)
                LoadCurrency(Conn)
                LoadExp(Conn)

                Application.DoEvents()

                LoadBaseStats(Conn)
                LoadPlayerSkills(Conn)

                Application.DoEvents()

                Conn.VitalPoints.HP = Conn.VitalPoints.MAXHP
                Conn.VitalPoints.MP = Conn.VitalPoints.MAXMP

                If Conn.IsGM Then
                    Output.AddLine("\B0\F5SV>\B8\F0 @GM GM Character '\B0\F8" & row("STR_NAME") & "\F0\B8'(\B0\F8" & struct.ID_CHARACTER & "\F0\B8) logged on by '" & _
                                 Conn.Username & "'(" & Conn.LoginID & ")")
                Else
                    Output.AddLine("\B0\F5SV>\B8\F0 ~~~ Character '\B0\F8" & row("STR_NAME") & "\F0\B8'(\B0\F8" & struct.ID_CHARACTER & "\F0\B8) logged on by '" & _
                                 Conn.Username & "'(" & Conn.LoginID & ")")
                End If

                ssql = "UPDATE TBL_LOGINS SET BYTE_SELECTED=" & struct.BYTE_SELECTED & " WHERE ID_LOGIN=" & Conn.LoginID & ";"
                DB.AccountDB.ExecuteNonQuery(ssql)

                Dim startinfo As New StartInfo

                If loadmap Then

                    'send the player their start coords
                    reply.PacketOpCode = PacketOpCode.Acknowledge
                    startinfo.LoadMapInfo.Posinfo.STR_MAP = Globals.iniServer.GetString("NEWCHAR", "MAP", "")
                    If IsMapOnServer(startinfo.LoadMapInfo.Posinfo.STR_MAP) Then
                        startinfo.LoadMapInfo.STR_MAPNAME = GetMapFromName(startinfo.LoadMapInfo.Posinfo.STR_MAP).name
                        startinfo.LoadMapInfo.Fmmap_Index = GetMapFromName(startinfo.LoadMapInfo.Posinfo.STR_MAP).Fmmap_Index
                    Else
                        startinfo.LoadMapInfo.STR_MAPNAME = ""
                        startinfo.LoadMapInfo.Fmmap_Index = 0
                    End If
                    startinfo.LoadMapInfo.Posinfo.INT2_X = Globals.iniServer.GetString("NEWCHAR", "X", "")
                    startinfo.LoadMapInfo.Posinfo.INT2_Y = Globals.iniServer.GetString("NEWCHAR", "Y", "")
                    startinfo.ShapeInfo = Conn.PlayerInfo.ShapeInfo
                    startinfo.VitalPoints = Conn.VitalPoints

                    Socket.SockServer.SendData(Protocol.MakePacket(reply, startinfo, Conn.Crypto), Conn.Index)

                    'add the player to the game
                    If IsMapOnServer(startinfo.LoadMapInfo.Posinfo.STR_MAP) Then AddPlayer(Conn, GetMapFromName(startinfo.LoadMapInfo.Posinfo.STR_MAP), startinfo.LoadMapInfo.Posinfo.INT2_X, startinfo.LoadMapInfo.Posinfo.INT2_Y, HUMAnimation.Standing, Direction.S)

                    If Not IsMapOnServer(startinfo.LoadMapInfo.Posinfo.STR_MAP) Then

                        System.Windows.Forms.Application.DoEvents()
                        System.Threading.Thread.Sleep(500)

                        SwitchServer(Conn, "", startinfo.LoadMapInfo.Posinfo)
                        loadmap = False

                    End If

                    Windows.Forms.Application.DoEvents()

                End If

                Threading.Thread.Sleep(100)

                Application.DoEvents()

                UpdatePlayerStats(Conn)
                Application.DoEvents()

                'load player info from the database
                LoadPlayerInventory(Conn)
                Application.DoEvents()

                LoadPlayerEquipment(Conn)
                Application.DoEvents()

                UpdatePlayerStats(Conn)
                Application.DoEvents()

                UpdatePlayersCharShape(Conn)
                Application.DoEvents()

                'set this players IsAlive flag to true
                Conn.IsAlive = True


                'write connection info to DB
                ssql = "UPDATE TBL_CHARACTER SET STR_LASTLOGIN='" & Database.Functions.TimeString() & "' WHERE ID_CHARACTER=" & struct.ID_CHARACTER & ";"
                DB.GameDB.ExecuteNonQuery(ssql)

                'run the login script
                If loadmap Then ServerScripting.Scripts.RunCommand("login.txt", "@onlogin", Conn)

                'sleep for 100ms to give time for game to sync up
                Application.DoEvents()
                Threading.Thread.Sleep(1000)

                If loadmap Then

                    UpdateUserList_Online(struct.ID_CHARACTER, row("STR_NAME"))

                    'tell the client to enter the game
                    reply.PacketType = GamePacketType.EnterGame
                    reply.PacketOpCode = PacketOpCode.Notify
                    Socket.SockServer.SendData(Protocol.MakePacket(reply, , Conn.Crypto), Conn.Index)

                End If

            Else
                GoTo fail
            End If

            Exit Sub

fail:

            reply.PacketOpCode = EvoLib.Protocol.mProtocol.PacketOpCode.NegAcknowledge
            Socket.SockServer.SendData(Protocol.MakePacket(reply, , Conn.Crypto), Conn.Index)

        End Sub

        Public Sub UpdateUserList_Online(id As Int64, name As String)

            Dim pkt As New Packet
            pkt.Username = Globals.ServerName
            pkt.PacketType = InterServerPacketType.UserLogin
            pkt.PacketOpCode = PacketOpCode.Notify

            Dim ulogin As PlayerOnlineInfo
            ulogin.ID_CHARACTER = id
            ulogin.STR_NAME = name

            Socket.ClusterComms.UDPBrocast.SendData(Protocol.MakePacket(pkt, ulogin))

        End Sub

        Public Sub UpdateUserList_Offline(id As Int64)

            Dim pkt As New Packet
            pkt.Username = Globals.ServerName
            pkt.PacketType = InterServerPacketType.UserLogout
            pkt.PacketOpCode = PacketOpCode.Notify

            Dim ulogin As New PlayerOnlineInfo
            ulogin.ID_CHARACTER = id

            Socket.ClusterComms.UDPBrocast.SendData(Protocol.MakePacket(pkt, ulogin))

        End Sub

        Private Sub TryMoveChar(ByVal struct As PlayerPositionInfo, ByRef Conn As Connection)
            Dim map As MirMap
            map = GetMapFromConn(Conn)
            MovePlayer(Conn, map, struct)
        End Sub

        Public Sub SendSystemMessage(Conn As SocketServer.Connection, txt As String)

            Dim outmsg As New CharChatMsg
            outmsg.msg.STR_MSG = txt
            outmsg.BYTE_TYPE = Protocol.ChatMsgType.System

            Dim pkt As Packet
            pkt.PacketType = GamePacketType.ChatMsg
            pkt.PacketOpCode = PacketOpCode.Notify
            pkt.Username = Conn.Username

            Socket.SockServer.SendData(MakePacket(pkt, outmsg, Conn.Crypto), Conn)

        End Sub

        Private Sub ChatMessage(ByVal struct As ChatMsg, ByRef Conn As Connection)

            Dim outmsg As New CharChatMsg

            Dim pkt As Packet
            pkt.PacketType = GamePacketType.ChatMsg
            pkt.PacketOpCode = PacketOpCode.Notify
            pkt.Username = Conn.Username

            Dim clusterPkt As New Packet
            clusterPkt.Username = Globals.ServerName
            clusterPkt.PacketOpCode = PacketOpCode.Notify
            clusterPkt.PacketType = InterServerPacketType.XServerChatMessage

            outmsg.STR_NAME = Conn.PlayerInfo.STR_NAME

            If Left(struct.STR_MSG, 2) = "!@" Then 'global shout
                outmsg.msg.STR_MSG = Right(struct.STR_MSG, struct.STR_MSG.Length - 2)
                outmsg.STR_NAME = Conn.PlayerInfo.STR_NAME

                'SendToAllInGame(pkt, outmsg)

                clusterPkt.PacketType = InterServerPacketType.XServerChatMessage
                outmsg.BYTE_TYPE = ChatMsgType.GlobalShout

                Socket.ClusterComms.UDPBrocast.SendData(Protocol.MakePacket(clusterPkt, outmsg))

                Logger.LoggerWriteLine("CHAT: [GLOBAL] [" & outmsg.STR_NAME & "] " & outmsg.msg.STR_MSG)

            ElseIf Left(struct.STR_MSG, 1) = "!" Then 'local shout
                outmsg.BYTE_TYPE = ChatMsgType.LocalShout
                outmsg.msg.STR_MSG = Right(struct.STR_MSG, struct.STR_MSG.Length - 1)
                outmsg.STR_NAME = Conn.PlayerInfo.STR_NAME

                'todo: send local shout packet
                SendToAllOnSameMap(Conn, pkt, outmsg)

                Logger.LoggerWriteLine("CHAT: [SHOUT (" & mMaps.GetMapFromConn(Conn).file & ")] [" & outmsg.STR_NAME & "] " & outmsg.msg.STR_MSG)

            ElseIf Left(struct.STR_MSG, 1) = "/" Then 'whisper
                outmsg.STR_TONAME = Left(struct.STR_MSG, InStr(struct.STR_MSG, " ") - 1)
                outmsg.STR_TONAME = Right(outmsg.STR_TONAME, outmsg.STR_TONAME.Length - 1)
                outmsg.STR_NAME = Conn.PlayerInfo.STR_NAME

                If Socket.HTTPStats.Data.OnlineUsers.isOnline(outmsg.STR_TONAME) Then

                    outmsg.BYTE_TYPE = ChatMsgType.Whisper
                    'todo: implement whisper handling
                    outmsg.msg.STR_MSG = Right(struct.STR_MSG, struct.STR_MSG.Length - InStr(struct.STR_MSG, " "))

                    clusterPkt.PacketType = InterServerPacketType.XServerChatMessage
                    outmsg.BYTE_TYPE = ChatMsgType.Whisper
                    Socket.ClusterComms.UDPBrocast.SendData(Protocol.MakePacket(clusterPkt, outmsg))

                    outmsg.BYTE_TYPE = ChatMsgType.SentWhisper
                    Socket.SockServer.SendData(Protocol.MakePacket(pkt, outmsg, Conn.Crypto), Conn)

                    Logger.LoggerWriteLine("CHAT: [WISPER (" & outmsg.STR_TONAME & ")] [" & outmsg.STR_NAME & "] " & outmsg.msg.STR_MSG)

                Else

                    outmsg.BYTE_TYPE = ChatMsgType.System
                    outmsg.msg.STR_MSG = outmsg.STR_TONAME & " is not online"

                    Socket.SockServer.SendData(Protocol.MakePacket(pkt, outmsg, Conn.Crypto), Conn)

                    Logger.LoggerWriteLine("CHAT: [WISPER (" & outmsg.STR_TONAME & ")] [" & outmsg.STR_NAME & "] NOT ONLINE FAILED")

                End If


            ElseIf Left(struct.STR_MSG, 2) = "@@" Then 'GM Shout
                If Conn.IsGM Then

                    'todo: implement whisper handling
                    outmsg.msg.STR_MSG = Right(struct.STR_MSG, struct.STR_MSG.Length - 2)

                    clusterPkt.PacketType = InterServerPacketType.XServerChatMessage
                    outmsg.BYTE_TYPE = ChatMsgType.Admin

                    Socket.ClusterComms.UDPBrocast.SendData(Protocol.MakePacket(clusterPkt, outmsg))
                    Socket.SockServer.SendData(Protocol.MakePacket(pkt, outmsg, Conn.Crypto), Conn)

                    Logger.LoggerWriteLine("CHAT: [GM SHOUT] [" & Conn.PlayerInfo.STR_NAME & "] " & outmsg.msg.STR_MSG)

                End If

            ElseIf Left(struct.STR_MSG, 1) = "@" Then 'System Commands
                Dim tmp As String = struct.STR_MSG
                Dim command As String
                tmp = Right(tmp, tmp.Length - 1)
                If InStr(tmp, " ") > 0 Then
                    command = Left(tmp, InStr(tmp, " ") - 1)
                    tmp = Right(tmp, tmp.Length - 1 - command.Length)
                Else
                    command = tmp
                    tmp = ""
                End If

                SystemCommands.SystemCommand(command, tmp, Conn)

            ElseIf Left(struct.STR_MSG, 2) = "!!" Then 'Group Chat


            Else 'normal

                outmsg.BYTE_TYPE = ChatMsgType.Normal
                outmsg.msg.STR_MSG = struct.STR_MSG
                outmsg.STR_NAME = Conn.PlayerInfo.STR_NAME

                SendToLocalPlayers(Conn, pkt, outmsg)

                Logger.LoggerWriteLine("CHAT: [MAP: " & mMaps.GetMapFromConn(Conn).file & " (" & Conn.PositionInfo.INT2_X & "," & Conn.PositionInfo.INT2_Y & ")] [" & outmsg.STR_NAME & "] " & outmsg.msg.STR_MSG)

            End If


        End Sub

        Public Sub ResyncPlayer(conn As Connection)

            Output.AddLine("\F5\B0SV>\F0\B8 " & GetCharAccString(conn) & " requested a resync")

            conn.PlayerWeight = New PlayerWeights

            LoadPlayerLooks(conn)
            LoadCurrency(conn)
            LoadExp(conn)
            LoadBaseStats(conn)
            LoadPlayerSkills(conn)

            Dim pkt As Packet
            pkt.Username = conn.Username
            pkt.PacketType = GamePacketType.Resync
            pkt.PacketOpCode = PacketOpCode.Answer

            Dim startinfo As StartInfo
            startinfo.LoadMapInfo.Posinfo.STR_MAP = GetMapFromConn(conn).file
            startinfo.LoadMapInfo.Posinfo.INT2_X = conn.PositionInfo.INT2_X
            startinfo.LoadMapInfo.Posinfo.INT2_Y = conn.PositionInfo.INT2_Y
            startinfo.ShapeInfo = conn.PlayerInfo.ShapeInfo
            startinfo.VitalPoints = conn.VitalPoints
            startinfo.LoadMapInfo.STR_MAPNAME = GetMapFromConn(conn).name
            startinfo.LoadMapInfo.Fmmap_Index = GetMapFromConn(conn).Fmmap_Index

            Socket.SockServer.SendData(Protocol.MakePacket(pkt, startinfo, conn.Crypto), conn.Index)

            LoadPlayerInventory(conn)
            LoadPlayerEquipment(conn)
            UpdatePlayerStats(conn)
            UpdatePlayersCharShape(conn)

            RemovePlayer(conn, GetMapFromName(startinfo.LoadMapInfo.Posinfo.STR_MAP))

            System.Windows.Forms.Application.DoEvents()

            AddPlayer(conn, GetMapFromName(startinfo.LoadMapInfo.Posinfo.STR_MAP), startinfo.LoadMapInfo.Posinfo.INT2_X, startinfo.LoadMapInfo.Posinfo.INT2_Y, HUMAnimation.Standing, Direction.S)

            System.Windows.Forms.Application.DoEvents()

            pkt.PacketOpCode = PacketOpCode.Acknowledge
            Socket.SockServer.SendData(Protocol.MakePacket(pkt, , conn.Crypto), conn.Index)

            '//////////////////////

            'LoadPlayerLooks(conn)
            'LoadCurrency(conn)
            'LoadExp(conn)

            'Application.DoEvents()

            'LoadBaseStats(conn)
            'LoadPlayerSkills(conn)

            'Application.DoEvents()

            'conn.VitalPoints.HP = conn.VitalPoints.MAXHP
            'conn.VitalPoints.MP = conn.VitalPoints.MAXMP

            'If conn.IsGM Then
            '    Output.AddLine("\B0\F5SV>\B8\F0 @GM GM Character '\B0\F8" & row("STR_NAME") & "\F0\B8'(\B0\F8" & struct.ID_CHARACTER & "\F0\B8) logged on by '" & _
            '                 conn.Username & "'(" & conn.LoginID & ")")
            'Else
            '    Output.AddLine("\B0\F5SV>\B8\F0 ~~~ Character '\B0\F8" & row("STR_NAME") & "\F0\B8'(\B0\F8" & struct.ID_CHARACTER & "\F0\B8) logged on by '" & _
            '                 conn.Username & "'(" & conn.LoginID & ")")
            'End If

            'ssql = "UPDATE TBL_LOGINS SET BYTE_SELECTED=" & struct.BYTE_SELECTED & " WHERE ID_LOGIN=" & conn.LoginID & ";"
            'DB.AccountDB.ExecuteNonQuery(ssql)

            'Dim startinfo As New StartInfo

            'If loadmap Then

            '    'send the player their start coords
            '    reply.PacketOpCode = PacketOpCode.Acknowledge
            '    startinfo.LoadMapInfo.Posinfo.STR_MAP = Globals.iniServer.GetString("NEWCHAR", "MAP", "")
            '    If IsMapOnServer(startinfo.LoadMapInfo.Posinfo.STR_MAP) Then
            '        startinfo.LoadMapInfo.STR_MAPNAME = GetMapFromName(startinfo.LoadMapInfo.Posinfo.STR_MAP).name
            '        startinfo.LoadMapInfo.Fmmap_Index = GetMapFromName(startinfo.LoadMapInfo.Posinfo.STR_MAP).Fmmap_Index
            '    Else
            '        startinfo.LoadMapInfo.STR_MAPNAME = ""
            '        startinfo.LoadMapInfo.Fmmap_Index = 0
            '    End If
            '    startinfo.LoadMapInfo.Posinfo.INT2_X = Globals.iniServer.GetString("NEWCHAR", "X", "")
            '    startinfo.LoadMapInfo.Posinfo.INT2_Y = Globals.iniServer.GetString("NEWCHAR", "Y", "")
            '    startinfo.ShapeInfo = conn.PlayerInfo.ShapeInfo
            '    startinfo.VitalPoints = conn.VitalPoints

            '    Socket.SockServer.SendData(Protocol.MakePacket(reply, startinfo, conn.Crypto), conn.Index)

            '    'add the player to the game
            '    If IsMapOnServer(startinfo.LoadMapInfo.Posinfo.STR_MAP) Then AddPlayer(conn, GetMapFromName(startinfo.LoadMapInfo.Posinfo.STR_MAP), startinfo.LoadMapInfo.Posinfo.INT2_X, startinfo.LoadMapInfo.Posinfo.INT2_Y, HUMAnimation.Standing, Direction.S)

            '    If Not IsMapOnServer(startinfo.LoadMapInfo.Posinfo.STR_MAP) Then

            '        System.Windows.Forms.Application.DoEvents()
            '        System.Threading.Thread.Sleep(500)

            '        SwitchServer(conn, "", startinfo.LoadMapInfo.Posinfo)
            '        loadmap = False

            '    End If

            '    Windows.Forms.Application.DoEvents()

            'End If

            'Threading.Thread.Sleep(100)

            'Application.DoEvents()

            'UpdatePlayerStats(conn)
            'Application.DoEvents()

            ''load player info from the database
            'LoadPlayerInventory(conn)
            'Application.DoEvents()

            'LoadPlayerEquipment(conn)
            'Application.DoEvents()

            'UpdatePlayerStats(conn)
            'Application.DoEvents()

            'UpdatePlayersCharShape(conn)
            'Application.DoEvents()

            ''set this players IsAlive flag to true
            'conn.IsAlive = True


            ''write connection info to DB
            'ssql = "UPDATE TBL_CHARACTER SET STR_LASTLOGIN='" & Database.Functions.TimeString() & "' WHERE ID_CHARACTER=" & struct.ID_CHARACTER & ";"
            'DB.GameDB.ExecuteNonQuery(ssql)

            ''run the login script
            'If loadmap Then ServerScripting.Scripts.RunCommand("login.txt", "@onlogin", conn)

            ''sleep for 100ms to give time for game to sync up
            'Application.DoEvents()
            'Threading.Thread.Sleep(1000)

            'If loadmap Then

            '    UpdateUserList_Online(struct.ID_CHARACTER, row("STR_NAME"))

            '    'tell the client to enter the game
            Dim reply As Packet
            reply.PacketType = GamePacketType.EnterGame
            reply.PacketOpCode = PacketOpCode.Notify
            reply.Username = conn.Username
            Socket.SockServer.SendData(Protocol.MakePacket(reply, , conn.Crypto), conn.Index)

            'End If

        End Sub

        Public Sub CheckXServerConn(conn As Connection)

            'save destination info to db
            Dim sSQL As String = "SELECT * FROM TBL_XSERVERCONN WHERE STR_DESTSERVER='" & Globals.ServerName & "' AND STR_IPADDRESS='" & conn.IP & "';"
            Dim col As Collection = DB.GameDB.ExecuteQueryFirstRecord(sSQL)

            If Not col Is Nothing Then
                If col.Count > 0 Then

                    sSQL = "DELETE FROM TBL_XSERVERCONN WHERE STR_IPADDRESS='" & conn.IP & "';"
                    DB.GameDB.ExecuteNonQuery(sSQL)

                    If col("STR_UNAME") <> conn.Username Then
                        Socket.SockServer.EndConnection(conn.Index)
                        Exit Sub
                    End If

                    sSQL = "SELECT STR_USERNAME, STR_PASSMD5 FROM TBL_LOGINS WHERE ID_LOGIN=" & col("ID_LOGIN") & " AND BOOL_DELETED='False';"
                    Dim row As Collection = DB.AccountDB.ExecuteQueryFirstRecord(sSQL)

                    Dim uid As UserLogin
                    uid.STR_USERNAME = row("STR_USERNAME")
                    'uid.STR_PASSMD5 = row("STR_PASSMD5")

                    'Packets.DoLogin(uid, conn)
                    System.Windows.Forms.Application.DoEvents()
                    System.Threading.Thread.Sleep(250)

                    sSQL = "SELECT BYTE_SELECTED FROM TBL_LOGINS WHERE ID_LOGIN=" & col("ID_LOGIN") & ";"
                    row = DB.AccountDB.ExecuteQueryFirstRecord(sSQL)

                    Dim SEL As SelectCharRequest
                    SEL.ID_CHARACTER = col("ID_CHARACTER")
                    SEL.BYTE_SELECTED = row("BYTE_SELECTED")

                    Packets.TrySelectChar(SEL, conn, False)
                    System.Windows.Forms.Application.DoEvents()
                    System.Threading.Thread.Sleep(250)

                    Dim posinfo As PositionInfo
                    posinfo.STR_MAP = col("STR_MAP")
                    posinfo.INT2_X = col("INT_X")
                    posinfo.INT2_Y = col("INT_Y")

                    Dim tryselreply As Packet
                    tryselreply.PacketType = LoginPacketType.TrySelectChar
                    tryselreply.PacketOpCode = PacketOpCode.Acknowledge
                    tryselreply.Username = conn.Username

                    Dim startinfo As StartInfo
                    startinfo.LoadMapInfo.Posinfo = posinfo
                    startinfo.LoadMapInfo.STR_MAPNAME = GetMapFromName(posinfo.STR_MAP).name
                    startinfo.ShapeInfo = conn.PlayerInfo.ShapeInfo
                    startinfo.VitalPoints = conn.VitalPoints

                    Socket.SockServer.SendData(Protocol.MakePacket(tryselreply, startinfo, conn.Crypto), conn.Index)
                    System.Windows.Forms.Application.DoEvents()
                    System.Threading.Thread.Sleep(500)

                    LoadPlayerInventory(conn)
                    LoadBaseStats(conn)
                    LoadPlayerEquipment(conn)
                    LoadCurrency(conn)
                    LoadExp(conn)

                    UpdatePlayerStats(conn)
                    UpdatePlayersCharShape(conn)

                    sSQL = "SELECT STR_NAME FROM TBL_CHARACTER WHERE ID_CHARACTER=" & col("ID_CHARACTER") & ";"
                    row = DB.GameDB.ExecuteQueryFirstRecord(sSQL)

                    UpdateUserList_Online(conn.CharacterID, row("STR_NAME"))

                    AddPlayer(conn, GetMapFromName(posinfo.STR_MAP), posinfo.INT2_X, posinfo.INT2_Y, HUMAnimation.Standing, Direction.S)
                    System.Windows.Forms.Application.DoEvents()
                    System.Threading.Thread.Sleep(2000)

                    'tell the client to enter the game
                    Dim reply As Packet
                    reply.PacketType = GamePacketType.EnterGame
                    reply.PacketOpCode = PacketOpCode.Notify
                    reply.Username = conn.Username

                    Socket.SockServer.SendData(Protocol.MakePacket(reply, , conn.Crypto), conn.Index)


                End If
            End If

        End Sub

    End Module

End Namespace